package com.itheima.em.server.service.impl.tianditu;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.em.config.AMapServerConfig;
import com.itheima.em.config.EagleConfig;
import com.itheima.em.config.TMapServerConfig;
import com.itheima.em.enums.ProviderType;
import com.itheima.em.mapper.TraceTerminalMapper;
import com.itheima.em.pojo.TraceServer;
import com.itheima.em.pojo.TraceTerminal;
import com.itheima.em.server.config.MybatisPlusConfig;
import com.itheima.em.service.EagleOrdered;
import com.itheima.em.service.TraceServerService;
import com.itheima.em.service.TraceTerminalService;
import com.itheima.em.util.SnowflakeIdGenerator;
import com.itheima.em.vo.PageResult;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 天地图的终端管理实现
 */
@Service("TMapTraceTerminalService")
@ConditionalOnBean({TMapServerConfig.class, MybatisPlusConfig.class})
public class TMapTraceTerminalServiceImpl extends ServiceImpl<TraceTerminalMapper, TraceTerminal> implements TraceTerminalService {

    /**
     * 雪花ID生成器
     */
    public SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(this.getClass().hashCode()%31, this.getProvider().getValue()); // 创建雪花ID生成器，传入机器ID和数据中心ID
    @Resource
    private EagleConfig eagleConfig;

    @Resource
    private TMapWebApiService tMapWebApiService;

    @Resource(name = "TMapTraceServerService")
    private TraceServerService traceServerService;

    /**
     * 创建终端
     *
     * @param serverId 服务id
     * @param name     名称
     * @param desc     描述
     * @param props    自定义字段
     * @return
     */
    @Override
    public String create(Long serverId, String name, String desc, Map<String, Object> props) {
        String propsJson = JSONUtil.toJsonStr(props);
        //获取到终端id返回
        Long terminalId = idGenerator.generateId();
        //将服务数据存储到数据库
        TraceTerminal traceTerminal = new TraceTerminal();
        traceTerminal.setProvider(ProviderType.TMAP);
        traceTerminal.setName(name);
        traceTerminal.setDesc(desc);
        traceTerminal.setServerId(serverId);
        traceTerminal.setProps(propsJson);
        traceTerminal.setTerminalId(terminalId);
        super.save(traceTerminal);

        return Convert.toStr(traceTerminal.getTerminalId());
    }

    /**
     * 不指定服务，由程序自动选择服务，如果没有可用的服务会自动创建服务
     *
     * @param name  名称
     * @param desc  描述
     * @param props 自定义字段
     * @return
     */
    @Override
    public String create(String name, String desc, Map<String, Object> props) {
        //查询可用的服务
        TraceServer traceServer = this.traceServerService.queryAvailableServer();
        Long serverId;
        if (null != traceServer) {
            serverId = traceServer.getServerId();
        } else {
            //创建新的服务
            String serverName = "MY-SERVER-" + DateUtil.format(new Date(), "yyyyMMdd");
            String serverDesc = "Service automatically created on " + DateUtil.now();
            String result = this.traceServerService.create(serverName, serverDesc);
            if (StrUtil.contains(result, "err")) {
                //服务创建失败
                return "err: Failed to create TMAP service.";
            }
            serverId = Convert.toLong(result);
        }
        return this.create(serverId, name, desc, props);
    }

    @Override
    public String delete(Long serverId, Long terminalId) {
        //删除数据库中的数据
        LambdaQueryWrapper<TraceTerminal> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TraceTerminal::getServerId, serverId);
        queryWrapper.eq(TraceTerminal::getTerminalId, terminalId);
        queryWrapper.eq(TraceTerminal::getProvider, ProviderType.TMAP);
        return super.remove(queryWrapper) ? null : "err";
    }

    @Override
    public String update(TraceTerminal traceTerminal) {
        //更新数据库中的数据
        LambdaQueryWrapper<TraceTerminal> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TraceTerminal::getServerId, traceTerminal.getServerId());
        queryWrapper.eq(TraceTerminal::getTerminalId, traceTerminal.getTerminalId());
        queryWrapper.eq(TraceTerminal::getProvider, ProviderType.TMAP);

        return super.update(traceTerminal, queryWrapper) ? null : "err";
    }

    @Override
    public PageResult<TraceTerminal> queryList(Long serverId, Long terminalId, String name, Integer page, Integer pageSize) {
        PageResult<TraceTerminal> pageResult = new PageResult<>();
        pageResult.setPage(page);
        pageResult.setPageSize(pageSize);
        pageResult.setItems(new ArrayList<>());
        if (null != terminalId) {
            //根据主键id查询
            pageResult.getItems().add(super.getById(terminalId));
            return pageResult;
        }

        if (StrUtil.isNotEmpty(name)) {
            //根据名称查询
            LambdaQueryWrapper<TraceTerminal> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.like(TraceTerminal::getName, name);
            queryWrapper.eq(TraceTerminal::getProvider, ProviderType.TMAP);
            queryWrapper.eq(TraceTerminal::getServerId, serverId);
            pageResult.setItems(super.list(queryWrapper));
            return pageResult;
        }

        //数据库查询列表
        LambdaQueryWrapper<TraceTerminal> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TraceTerminal::getProvider, ProviderType.TMAP);
        queryWrapper.eq(TraceTerminal::getServerId, serverId);
        queryWrapper.orderByDesc(TraceTerminal::getCreated);

        Page<TraceTerminal> traceTerminalPage = new Page<>(page, pageSize);

        Page<TraceTerminal> terminalPage = super.page(traceTerminalPage, queryWrapper);
        return pageResult.convert(terminalPage);
    }
    /**
     * 查询终端在某个轨迹中的最新位置
     *
     * @param serverId   服务id
     * @param terminalId 终端id
     * @param traceId    轨迹id
     * @return 服务商响应的数据
     */
    @Override
    public String queryLastPoint(Long serverId, Long terminalId, Long traceId) {
//        TODO
        return "err";
    }

    @Override
    public int getOrder() {
        return EagleOrdered.ONE;
    }

    @Override
    public ProviderType getProvider() {
        return ProviderType.TMAP;
    }
}
